// Copyright (C) 1953-2022 NUDT
// Verilog module name - clock_timing_and_correcting 
// Version: V4.0.0.20221115
// Created:
//         by - fenglin 
////////////////////////////////////////////////////////////////////////////
// Description:
//         global time synchronization 
//         generate report pulse base on global time
///////////////////////////////////////////////////////////////////////////

`timescale 1ns / 1ps

module clock_timing_and_correcting
#(
    parameter clk_period = {8'd8,41'h0}//8ns
 ) 
(
        i_clk                  ,
        i_rst_n                ,
       
        iv_syn_clock_set       ,
        i_syn_clock_set_wr     ,

        iv_frequency_cor       ,
        i_frequency_cor_wr     ,

        ov_complete_clk        ,
        ov_frequency_cor
);
// clk & rst
input                  i_clk;
input                  i_rst_n;

input      [95:0]      iv_syn_clock_set       ;
input                  i_syn_clock_set_wr     ;

input      [48:0]      iv_frequency_cor       ;
input                  i_frequency_cor_wr     ;

output reg [120:0]     ov_complete_clk        ;
//assign ov_global_time_cycle = iv_syn_clock_cycle;
output reg [48:0]      ov_frequency_cor       ;
always @(posedge i_clk or negedge i_rst_n) begin
    if(!i_rst_n)begin
        ov_frequency_cor        <= clk_period;      
    end
    else begin
        if(i_frequency_cor_wr)begin
            ov_frequency_cor        <= iv_frequency_cor;
        end
        else begin
            ov_frequency_cor        <= ov_frequency_cor;
        end        
    end
end

always @(posedge i_clk or negedge i_rst_n) begin
    if(!i_rst_n)begin
        ov_complete_clk        <= 121'b0;    
    end
    else begin  
        if(i_syn_clock_set_wr)begin  //sync clock < sync clock cycle,correct sync clock        
			if({iv_syn_clock_set[47:0],25'b0} + ov_frequency_cor[48:0] >= {32'd1000000000,41'b0})begin
				ov_complete_clk[120:73]  <= iv_syn_clock_set[95:48] + 1'b1;
				ov_complete_clk[72:0]    <= {iv_syn_clock_set[47:0],25'b0} + ov_frequency_cor[48:0] - {32'd1000000000,41'b0};
				//ov_complete_clk[40:0]    <= ov_frequency_cor[40:0];
			end
			else begin
				ov_complete_clk[120:73]  <= iv_syn_clock_set[95:48];
				ov_complete_clk[72:0]    <= {iv_syn_clock_set[47:0],25'b0} + ov_frequency_cor[48:0];
				//ov_complete_clk[40:0]    <= ov_frequency_cor[40:0];
			end                                                                     
        end                  
        else begin//correct frequence of sync clock.
            if({1'b0,ov_complete_clk[40:0]} + {1'b0,ov_frequency_cor[40:0]} >= 42'h200_0000_0000)begin
                ov_complete_clk[40:0]  <= {1'b0,ov_complete_clk[40:0]} + {1'b0,ov_frequency_cor[40:0]} - 42'h200_0000_0000;  
                if(ov_complete_clk[72:41] + ov_frequency_cor[48:41] + 1'd1 >= 32'd1000000000)begin
                    ov_complete_clk[120:73]  <= ov_complete_clk[120:73] + 1'b1;
					ov_complete_clk[72:41]   <= ov_complete_clk[72:41] + ov_frequency_cor[48:41] + 1'd1 - 32'd1000000000;
                end
                else begin
                    ov_complete_clk[120:73]  <= ov_complete_clk[120:73];
					ov_complete_clk[72:41]   <= ov_complete_clk[72:41] + ov_frequency_cor[48:41] + 1'd1;
                end
            end
            else begin
                ov_complete_clk[40:0]  <= ov_complete_clk[40:0] + ov_frequency_cor[40:0];  
                if(ov_complete_clk[72:41] + ov_frequency_cor[48:41] >= 32'd1000000000)begin
                    ov_complete_clk[120:73]  <= ov_complete_clk[120:73] + 1'b1;
					ov_complete_clk[72:41]   <= ov_complete_clk[72:41] + ov_frequency_cor[48:41] - 32'd1000000000;
                end
                else begin
                    ov_complete_clk[120:73]  <= ov_complete_clk[120:73];
					ov_complete_clk[72:41]   <= ov_complete_clk[72:41] + ov_frequency_cor[48:41];
                end                            
            end 
        end
    end
end
endmodule